home *** CD-ROM | disk | FTP | other *** search
/ Java 1996 August / Java - Summer 1996.iso / kaffe-0.2 / kaffe / threadCalls.c < prev    next >
C/C++ Source or Header  |  1996-02-18  |  4KB  |  202 lines

  1. /*
  2.  * threadCalls.c
  3.  * Support for threaded ops which may block (read, write, connect, etc.).
  4.  *
  5.  * Copyright (c) 1996 Systems Architecture Research Centre,
  6.  *           City University, London, UK.
  7.  *
  8.  * See the file "license.terms" for information on usage and redistribution
  9.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10.  *
  11.  * Written by Tim Wilkinson <tim@sarc.city.ac.uk>, February 1996.
  12.  */
  13.  
  14. #include <sys/types.h>
  15. #include <errno.h>
  16. #include <assert.h>
  17. #include <sys/socket.h>
  18. #include <sys/time.h>
  19. #include "object.h"
  20. #include "thread.h"
  21.  
  22. #define    TH_READ        0
  23. #define    TH_WRITE    1
  24.  
  25. static int maxFd;
  26. static fd_set readsPending;
  27. static fd_set writesPending;
  28. static thread* readQ[FD_SETSIZE];
  29. static thread* writeQ[FD_SETSIZE];
  30. static struct timeval tm = { 0, 0 };
  31.  
  32. static void blockOnFile(int, int);
  33.  
  34. void waitOnEvents(void);
  35.  
  36. /*
  37.  * Threaded create socket.
  38.  */
  39. int
  40. threadedCreateSocket(int af, int type, int proto)
  41. {
  42.     int fd = socket(af, type, proto);
  43.  
  44.     /* Make non-blocking and I/O signalling here */
  45.  
  46.     return (fd);
  47. }
  48.  
  49. /*
  50.  * Threaded socket connect.
  51.  */
  52. int
  53. threadedConnect(int fd, struct sockaddr* addr, int len)
  54. {
  55.     int r;
  56.  
  57.     r = connect(fd, addr, len);
  58.     if (r < 0 & (errno == EINPROGRESS || errno == EALREADY)) {
  59.         blockOnFile(fd, TH_READ);
  60.         r = 0; /* Assume it's okay when we get released */
  61.     }
  62.  
  63.     return (r);
  64. }
  65.  
  66. /*
  67.  * Threaded socket accept.
  68.  */
  69. int
  70. threadedAccept(int fd, struct sockaddr* addr, int* len)
  71. {
  72.     int r;
  73.  
  74.     for (;;) {
  75.         r = accept(fd, addr, len);
  76.         if (r >= 0 || !(errno == EINPROGRESS || errno == EALREADY)) {
  77.             break;
  78.         }
  79.         blockOnFile(fd, TH_READ);
  80.     }
  81.  
  82.     return (r);
  83. }
  84.  
  85. /*
  86.  * Read but only if we can.
  87.  */
  88. int
  89. threadedRead(int fd, char* buf, int len)
  90. {
  91.     int r;
  92.     char* ptr;
  93.  
  94.     ptr = buf;
  95.     do {
  96.         r = read(fd, ptr, len);
  97.         if (r < 0 && errno == EWOULDBLOCK) {
  98.             blockOnFile(fd, TH_READ);
  99.             continue;
  100.         }
  101.         ptr += r;
  102.         len -= r;
  103.  
  104.     } while (len > 0 && r > 0);
  105.  
  106.     return (ptr - buf);
  107. }
  108.  
  109. /*
  110.  * Write but only if we can.
  111.  */
  112. int
  113. threadedWrite(int fd, char* buf, int len)
  114. {
  115.     int r;
  116.     char* ptr;
  117.  
  118.     ptr = buf;
  119.     do {
  120.         r = write(fd, ptr, len);
  121.         if (r < 0 && errno == EWOULDBLOCK) {
  122.             blockOnFile(fd, TH_WRITE);
  123.             continue;
  124.         }
  125.         ptr += r;
  126.         len -= r;
  127.  
  128.     } while (len > 0 && r > 0);
  129.  
  130.     return (ptr - buf);
  131. }
  132.  
  133. /*
  134.  * An attempt to access a file would block, so suspend the thread until
  135.  * it will happen.
  136.  */
  137. static
  138. void
  139. blockOnFile(int fd, int op)
  140. {
  141.     if (fd > maxFd) {
  142.         maxFd = fd;
  143.     }
  144.     if (op == TH_READ) {
  145.         FD_SET(fd, &readsPending);
  146.         suspendOnQThread(currentThread, &readQ[fd]);
  147.         FD_CLR(fd, &readsPending);
  148.     }
  149.     else {
  150.         FD_SET(fd, &writesPending);
  151.         suspendOnQThread(currentThread, &writeQ[fd]);
  152.         FD_CLR(fd, &writesPending);
  153.     }
  154. }
  155.  
  156. /*
  157.  * Check if some file descriptor or other event to become ready.
  158.  *  Block if required.
  159.  */
  160. void
  161. checkEvents(bool block)
  162. {
  163.     int r;
  164.     fd_set rd;
  165.     fd_set wr;
  166.     thread* tid;
  167.     thread* ntid;
  168.     int i;
  169.  
  170.     intsDisable();
  171.  
  172. #if defined(FD_COPY)
  173.     FD_COPY(&readsPending, &rd);
  174.     FD_COPY(&writesPending, &wr);
  175. #else
  176.     bcopy(&readsPending, &rd, sizeof(rd));
  177.     bcopy(&writesPending, &wr, sizeof(wr));
  178. #endif
  179.     r = select(maxFd, &rd, &wr, 0, (block ? 0 : &tm));
  180.  
  181.     for (i = 0; r > 0 && i < maxFd; i++) {
  182.         if (readQ[i] != 0 && FD_ISSET(i, &readsPending)) {
  183.             for (tid = readQ[i]; tid != 0; tid = ntid) {
  184.                 ntid = tid->next;
  185.                 resumeThread(tid);
  186.             }
  187.             readQ[i] = 0;
  188.             r--;
  189.         }
  190.         if (writeQ[i] != 0 && FD_ISSET(i, &writesPending)) {
  191.             for (tid = writeQ[i]; tid != 0; tid = ntid) {
  192.                 ntid = tid->next;
  193.                 resumeThread(tid);
  194.             }
  195.             writeQ[i] = 0;
  196.             r--;
  197.         }
  198.     }
  199.  
  200.     intsRestore();
  201. }
  202.